/*
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
 * MA  02110-1301, USA.
 *
 * http://www.gnu.org/copyleft/gpl.html
 */
package com.aionemu.gameserver.network.aion;

import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SocketChannel;

import org.apache.log4j.Logger;

import com.aionemu.commons.network.mmocore.MMOConnection;
import com.aionemu.commons.network.mmocore.SelectorThread;
import com.aionemu.commons.network.mmocore.State;
import com.aionemu.gameserver.model.account.Account;
import com.aionemu.gameserver.model.gameobjects.player.Player;
import com.aionemu.gameserver.network.Crypt;
import com.aionemu.gameserver.network.aion.serverpackets.SM_KEY;
import com.aionemu.gameserver.network.loginserver.LoginServer;
import com.aionemu.gameserver.services.PlayerService;

/**
 * @author Mr. Poke
 *
 */
public class GameClient extends MMOConnection<GameClient>
{
	private static final Logger	log		= Logger.getLogger(GameClient.class);
	
	/**
	 * Crypt that will encrypt/decrypt packets.
	 */
	private final Crypt			crypt	= new Crypt();

	/**
	 * AionClient is authenticating by passing to GameServer id of account.
	 */
	private Account				account;

	/**
	 * active Player that owner of this connection is playing [entered game]
	 */
	private Player				activePlayer;

	private volatile boolean disconnected;
	/**
	 * @param selectorThread
	 * @param socketChannel
	 * @throws ClosedChannelException
	 */
	protected GameClient(SelectorThread<GameClient> selectorThread, SocketChannel socketChannel) throws ClosedChannelException
	{
		super(selectorThread, socketChannel);
		sendPacket(new SM_KEY());
		log.debug("Client connected Ip: " + getHostAddress());
	}

	public final int enableCryptKey()
	{
		return crypt.enableKey();
	}

	public Player getActivePlayer()
	{
		return activePlayer;
	}

	public Account getAccount()
	{
		return account;
	}

	/**
	 * @param account The account to set.
	 */
	public void setAccount(Account account)
	{
		this.account = account;
	}

	public boolean setActivePlayer(Player player)
	{
		if (activePlayer != null && player != null)
			return false;
		activePlayer = player;

		if (activePlayer == null)
			state = State.AUTHED;
		else
			state = State.ENTERED;
		return true;
	}
	/* (non-Javadoc)
	 * @see com.aionemu.commons.network.mmocore.MMOConnection#onDisconnection()
	 */
	@Override
	protected void onDisconnection()
	{
		setDisconnected();
	}

	void setDisconnected()
	{
		if (account != null)
		{
			LoginServer.getInstance().aionClientDisconnected(account.getId());
			account = null;
		}

		if (getActivePlayer() != null)
		{
			Player player = getActivePlayer();

			if (player.isInShutdownProgress())
				PlayerService.playerLoggedOut(player);

			// prevent ctrl+alt+del / close window exploit
			else
			{
				int delay = 15;
				PlayerService.playerLoggedOutDelay(player, (delay * 1000));
			}
			log.info("Player disconnected! Name: " + player.getName());
		}
		disconnected = true;
	}

	boolean isDisconnected()
	{
		return disconnected;
	}

	/* (non-Javadoc)
	 * @see com.aionemu.commons.network.mmocore.MMOConnection#onForcedDisconnection()
	 */
	@Override
	protected void onForcedDisconnection()
	{
		log.debug("Client " + toString() + " disconnected abnormally.");
	}

	/* (non-Javadoc)
	 * @see com.aionemu.commons.network.mmocore.MMOConnection#decrypt(java.nio.ByteBuffer, int)
	 */
	@Override
	protected boolean decrypt(ByteBuffer buf, int size)
	{
		return crypt.decrypt(buf, size);
	}

	/* (non-Javadoc)
	 * @see com.aionemu.commons.network.mmocore.MMOConnection#encrypt(java.nio.ByteBuffer, int)
	 */
	@Override
	protected void encrypt(ByteBuffer buf, int size)
	{
		crypt.encrypt(buf, size);
		buf.position(buf.position() + size);
	}

	/* (non-Javadoc)
	 * @see com.aionemu.commons.network.mmocore.MMOConnection#getUID()
	 */
	@Override
	protected String getUID()
	{
		return account == null ? "" : account.getName();
	}

}
